#include "qdataconnection.h"

QDataConnection::QDataConnection(QWidget *parent) :
  QWidget(parent)
{

  tcpSocket = new QTcpSocket;
  udpSocket = new QUdpSocket;
  serialPort = new QextSerialPort("COM1",QextSerialPort::EventDriven);
  connConfig.connName = QString("Untitled");
  connConfig.connType = TCP;
  connConfig.addr_port = QString("127.0.0.1");
  connConfig.port_baud = 50500;
  connConfig.connState = INACTIVE;
  connConfig.connID = 0;
}

QString QDataConnection::getName()
{
  return connConfig.connName;
}

connectionType QDataConnection::getType()
{
  return connConfig.connType;
}

QString QDataConnection::getAddress_Port()
{
  return connConfig.addr_port;
}

quint16 QDataConnection::getPort_Baud()
{
  return connConfig.port_baud;
}

connectionState QDataConnection::getState()
{
  return connConfig.connState;
}

void QDataConnection::setName(QString newName)
{
  connConfig.connName = newName;
}

void QDataConnection::setType(connectionType newType)
{
  connConfig.connType = newType;
}

void QDataConnection::setAddress_Port(QString newAddress)
{
  connConfig.addr_port = newAddress;
}

void QDataConnection::setPort_Baud(quint16 newPort)
{
  connConfig.port_baud = newPort;
}

void QDataConnection::setID(quint16 newID)
{
  connConfig.connID = newID;
}

void QDataConnection::dataConnect()
{
  QString serialPrefix = QString("\\\\.\\");
  switch(connConfig.connType)
  {
  case TCP:
    tcpSocket->connectToHost(QHostAddress(connConfig.addr_port),connConfig.port_baud);
    if(tcpSocket->waitForConnected(5000))
    {
      connConfig.connState = ACTIVE;
      connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(dataAvailable()));
      connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(disconnected()));
    }
    else
    {
      connConfig.connState = INACTIVE;
    }

    break;
  case UDP:
    udpSocket->bind(QHostAddress(connConfig.addr_port),connConfig.port_baud,QUdpSocket::ShareAddress);
//    udpSocket->bind(connConfig.port_baud,QUdpSocket::ShareAddress);
     connConfig.connState = ACTIVE;
     connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataAvailable()));
//    if(udpSocket->waitForConnected(5000))
//    {
//      connConfig.connState = ACTIVE;
//      connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataAvailable()));
//      connect(udpSocket,SIGNAL(disconnected()),this,SLOT(disconnected));
//    }
//    else
//    {
//      connConfig.connState = INACTIVE;
//    }
    break;
  case SERIAL:
    serialPrefix.append(connConfig.addr_port);
    serialPort->setPortName(serialPrefix);
    switch(connConfig.port_baud)
    {
    case B4800:
      serialPort->setBaudRate(BAUD4800);
      break;
    case B9600:
      serialPort->setBaudRate(BAUD9600);
      break;
    case B19200:
      serialPort->setBaudRate(BAUD19200);
      break;
    case B57600:
      serialPort->setBaudRate(BAUD57600);
      break;
    case B115200:
      serialPort->setBaudRate(BAUD115200);
      break;
    default:
      serialPort->setBaudRate(BAUD115200);
      break;
    }
    serialPort->setFlowControl(FLOW_OFF);
    serialPort->setParity(PAR_NONE);
    serialPort->setDataBits(DATA_8);
    serialPort->setStopBits(STOP_1);
    if(serialPort->open(QIODevice::ReadWrite) == true)
    {
      connConfig.connState=ACTIVE;
      connect(serialPort,SIGNAL(readyRead()),this,SLOT(dataAvailable()));
      connect(serialPort,SIGNAL(aboutToClose()),this,SLOT(disconnected()));
    }
    else
    {
      connConfig.connState=INACTIVE;
    }
    break;
  default:
    break;
  }
  connectionChanged();
}

void QDataConnection::dataDisconnect()
{
  switch(connConfig.connType)
  {
  case TCP:
    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(dataAvailable()));
    disconnect(tcpSocket,SIGNAL(disconnected()),this,SLOT(disconnected()));
    tcpSocket->disconnectFromHost();
    tcpSocket->abort();
    connConfig.connState=INACTIVE;
    break;
  case UDP:
    disconnect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataAvailable()));
//    disconnect(udpSocket,SIGNAL(disconnected()),this,SLOT(disconnected()));
//    udpSocket->disconnectFromHost();
    udpSocket->close();
    udpSocket->abort();
    connConfig.connState=INACTIVE;
    break;
  case SERIAL:
    disconnect(serialPort,SIGNAL(readyRead()),this,SLOT(dataAvailable()));
    disconnect(serialPort,SIGNAL(aboutToClose()),this,SLOT(disconnected()));
    serialPort->close();
    connConfig.connState=INACTIVE;
    break;
  default:
    break;
  }
  connectionChanged();
}

void QDataConnection::dataAvailable()
{
  QByteArray bytebuf;
  QHostAddress sender;
  quint16 senderPort;
  switch(connConfig.connType)
  {
  case TCP:
    while(tcpSocket->bytesAvailable())
    {
      bytebuf.append(tcpSocket->readAll());
    }
    break;
  case UDP:
    while(udpSocket->bytesAvailable())
    {
      bytebuf.resize(udpSocket->pendingDatagramSize());
      udpSocket->readDatagram(bytebuf.data(), bytebuf.size(),
                              &sender, &senderPort);
    }
  case SERIAL:
    while(serialPort->bytesAvailable())
    {
      bytebuf.append(serialPort->readAll());
    }
  default:
    break;
  }
  emit dataIn(connConfig,bytebuf);
}

void QDataConnection::dataOut(QByteArray dataout)
{
  switch(connConfig.connType)
  {
  case TCP:
    if(tcpSocket->ConnectedState)
      tcpSocket->write(dataout);
    break;
  case UDP:
    if(udpSocket->ConnectedState)
      udpSocket->write(dataout);
    break;
  case SERIAL:
    if(serialPort->isOpen())
    {
      serialPort->write(dataout);
    }
    break;
  default:
    break;
  }
}

void QDataConnection::disconnected()
{
  connConfig.connState = INACTIVE;
  connectionChanged();
}

void QDataConnection::connectionChanged()
{
  emit connectionStatus(connConfig.connState);
}



